package pkg

import (
	"fmt"
	"os"
	"path/filepath"
	"time"

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

var (
	globalLogger *zap.Logger
	logLevel     zapcore.Level
)

// 初始化日志配置
func ZapInit(logDir, level string) error {
	// 创建日志目录
	if err := os.MkdirAll(logDir, 0755); err != nil {
		return fmt.Errorf("创建日志目录失败: %w", err)
	}

	// 解析日志级别
	switch level {
	case "debug":
		logLevel = zapcore.DebugLevel
	case "info":
		logLevel = zapcore.InfoLevel
	case "warn":
		logLevel = zapcore.WarnLevel
	case "error":
		logLevel = zapcore.ErrorLevel
	default:
		logLevel = zapcore.InfoLevel
	}

	// 日志文件名 (按日期滚动)
	logFileName := fmt.Sprintf("app_%s.log", time.Now().Format("20060102"))
	logPath := filepath.Join(logDir, logFileName)

	// 配置编码器
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",
		LevelKey:       "level",
		CallerKey:      "caller",
		MessageKey:     "msg",
		StacktraceKey:  "stack",
		LineEnding:     zapcore.DefaultLineEnding,
		EncodeLevel:    zapcore.CapitalLevelEncoder,   // 大写级别(DEBUG/INFO)
		EncodeTime:     customTimeEncoder,             // 自定义时间格式
		EncodeCaller:   zapcore.ShortCallerEncoder,    // 短路径调用者(如:logger/log.go:45)
		EncodeDuration: zapcore.StringDurationEncoder, // 时长格式化
	}

	// 创建日志文件写入器
	fileWriter, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
	if err != nil {
		return fmt.Errorf("打开日志文件失败: %w", err)
	}

	// 多输出目标配置 (文件+控制台)
	core := zapcore.NewTee(
		// 写入文件的核心配置
		zapcore.NewCore(
			zapcore.NewJSONEncoder(encoderConfig), // JSON格式
			zapcore.AddSync(fileWriter),
			zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
				return lvl >= logLevel
			}),
		),
		// 输出到控制台的核心配置
		zapcore.NewCore(
			zapcore.NewConsoleEncoder(encoderConfig), // 控制台格式
			zapcore.AddSync(os.Stdout),
			zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
				return lvl >= logLevel && os.Getenv("ENV") != "production" // 生产环境不输出到控制台
			}),
		),
	)

	// 创建日志实例
	globalLogger = zap.New(
		core,
		zap.AddCaller(),                   // 记录调用位置
		zap.AddStacktrace(zap.ErrorLevel), // 错误级别以上记录堆栈
		zap.AddCallerSkip(1),              // 跳过当前包装层，显示真实调用位置
	)
	return nil
}

// 自定义时间编码器
func customTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
	enc.AppendString(t.Format("2006-01-02 15:04:05.000"))
}

// 以下是各等级日志的封装方法

// Debug 调试级别日志
func Debug(msg string, fields ...zap.Field) {
	if globalLogger != nil {
		globalLogger.Debug(msg, fields...)
	}
}

// Info 信息级别日志
func Info(msg string, fields ...zap.Field) {
	if globalLogger != nil {
		globalLogger.Info(msg, fields...)
	}
}

// Warn 警告级别日志
func Warn(msg string, fields ...zap.Field) {
	if globalLogger != nil {
		globalLogger.Warn(msg, fields...)
	}
}

// Error 错误级别日志
func Error(msg string, fields ...zap.Field) {
	if globalLogger != nil {
		globalLogger.Error(msg, fields...)
	}
}

// Fatal 致命错误日志(会触发程序退出)
func Fatal(msg string, fields ...zap.Field) {
	if globalLogger != nil {
		globalLogger.Fatal(msg, fields...)
	}
}

// Sync 刷新日志到磁盘
func Sync() error {
	if globalLogger != nil {
		return globalLogger.Sync()
	}
	return nil
}

// 常用辅助方法 - 快速记录带结构体的日志
func InfoStruct(msg string, data interface{}) {
	Info(msg, zap.Reflect("data", data))
}

func ErrorStruct(msg string, err error, data interface{}) {
	Error(msg, zap.Error(err), zap.Reflect("data", data))
}
